package org.deltaset.samples.mvc.web;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.deltaset.faces.component.SelectOption;
import org.deltaset.meta.CollectionHandler;
import org.deltaset.meta.MetaAction;
import org.deltaset.meta.MetaActionHandler;
import org.deltaset.meta.MetaField;
import org.deltaset.meta.OptionBuilder;

/**
 *
 * @author dmakariev
 */
public class MetaHelper {

    private final MetaActionHandler actionHandler;
    private final CollectionHandler collectionHandler;
    private final MetaActionCache metaActionCache;
    private final DateFormat dateFormat;
    private final Map<String, String> metaErrors;
    private final OptionBuilder<SelectOption> optionBuilder;

    public MetaHelper(OptionBuilder<SelectOption> optionBuilder, MetaActionCache metaActionCache, MetaActionHandler actionHandler, CollectionHandler collectionHandler, DateFormat dateFormat) {
        this.metaActionCache = metaActionCache;
        this.actionHandler = actionHandler;
        this.collectionHandler = collectionHandler;
        this.dateFormat = dateFormat;
        this.metaErrors = new HashMap<String, String>();
        this.optionBuilder = optionBuilder;
    }

    public String actionId(MetaAction metaAction) {
        return metaActionCache.getMetaActionId(metaAction);
    }

//    public MetaAction getMetaActionById(String key) {
//        return metaActionCache.getMetaActionById(key);
//    }
    public String getModelId(final Object item) {
        return this.actionHandler.getModelId(item);
    }

    public String modelTitle(final Object item) {
        return this.actionHandler.modelTitle(item);
    }

    public List convertToList(Collection c) {
        return this.collectionHandler.convertToList(c);
    }

    public boolean hasErrors() {
        return !this.metaErrors.isEmpty();
    }

    public void addError(String key, String message) {
        this.metaErrors.put(key, message);
    }

    public boolean hasErrorFor(String key) {
        return this.metaErrors.containsKey(key);
    }

    public String errorFor(String key) {
        return this.metaErrors.get(key);
    }

    public List<String> getErrors() {
        final List<String> messages = new ArrayList<String>(this.metaErrors.values());
        return messages;
    }

    public String formatDate(Date date) {
        if (null == date) {
            return "";
        }
        final String formattedDate = dateFormat.format(date);
        return formattedDate;
    }

    public List<MvcSelectOption> selectOptions(final MetaField metaField, final Object valueObject) {

        final List<SelectOption> options = optionBuilder.getOptions(metaField);
        final String valueObjectSelectId = selectId(valueObject);

        final List<MvcSelectOption> resultOptions = new ArrayList<MvcSelectOption>();
        for (SelectOption selectOption : options) {
            final String label = selectOption.getSelectLabel();
            final String value = selectId(selectOption.getSelectValue());
            final boolean selected = valueObjectSelectId.equals(value);
            final MvcSelectOption option = new MvcSelectOption(label, value, selected);
            resultOptions.add(option);
        }
        return resultOptions;
    }

    private String selectId(final Object item) {
        if (null == item) {
            return "";
        }
        if (item.getClass().isEnum()) {
            return ((Enum) item).name();
        } else {
            return this.actionHandler.getModelId(item);
        }
    }

    public static class MvcSelectOption {

        private final String label;
        private final String value;
        private final boolean selected;

        public MvcSelectOption(String label, String value, boolean selected) {
            this.label = label;
            this.value = value;
            this.selected = selected;
        }

        public String getLabel() {
            return label;
        }

        public String getValue() {
            return value;
        }

        public boolean isSelected() {
            return selected;
        }
    }
}
